/*
 * Licensed to the 南京汇海交通科技有限公司
 *
 * Copyright (c) 2025.
 * All rights reserved.
 *
 * 本软件属南京汇海交通科技有限公司所有，在未获得南京汇海交通科技有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.chframework.http.handler;

import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.chframework.http.utility.HttpResponseEntity;
import com.chframework.http.utility.ServiceConfigInfo;
import com.chframework.http.utility.ServiceConfigInfo.ServiceRequestConfigInfo;
import com.chframework.http.utility.ServiceConfigInfo.ParamProperty;
import com.chframework.http.utility.constant.HttpServiceFieldConstant;
import com.chframework.http.utility.constant.IsSuccessEnum;
import org.springframework.http.HttpStatus;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * HTTP请求对象 - 抽象类(扩展)
 */
public abstract class HttpRequestHandler {

    protected HttpResponseEntity response;
    protected ServiceRequestConfigInfo serviceRequestConfigInfo;
    protected Map<String, String> requestHeaderMap = new HashMap<>();
    protected Map<String, Object> requestFormMap = new HashMap<>();
    protected String requestUrl;
    protected String urlParam;
    protected String jsonBody;

    /**
     * 根据 配置逻辑 执行 HTTP 请求
     *
     * @param serviceConfigInfo HTTP请求配置
     * @return 返回 执行 HTTP 请求 响应结果
     */
    public HttpResponseEntity sendHttpRequest(ServiceConfigInfo serviceConfigInfo) {
        serviceRequestConfigInfo = serviceConfigInfo.getServiceRequestConfigInfo();
        this.requestHeaderMap.putAll(
                serviceRequestConfigInfo.getHeaderParamConfig()
                        .parallelStream()
                        .collect(
                                Collectors.toMap(ParamProperty::getSourceParamPath,
                                        ParamProperty::getSourceParamValue,
                                        (oldValue, newValue) -> newValue)
                        )
        );
        this.requestFormMap.putAll(
                serviceRequestConfigInfo.getFormParamConfig()
                        .parallelStream()
                        .collect(
                                Collectors.toMap(ParamProperty::getSourceParamPath,
                                        ParamProperty::getSourceParamValue,
                                        (oldValue, newValue) -> newValue)
                        )
        );
        this.urlParam = serviceRequestConfigInfo.getQueryParamConfig()
                .parallelStream()
                .map(t -> t.getSourceParamPath() + "=" + t.getSourceParamValue())
                .collect(Collectors.joining("&"));
        this.requestUrl = urlParam.length() > 0
                ? serviceRequestConfigInfo.getRequestUrl() + "?" + urlParam
                : serviceRequestConfigInfo.getRequestUrl();
        this.jsonBody = serviceRequestConfigInfo.getRequestBody();

        // 5.0 创建响应结果对象
        this.response = new HttpResponseEntity();
        response.setId(IdUtil.objectId());
        response.setIsSuccess(IsSuccessEnum.SUCCESS);
        response.setExceptionStack(null);

        try {
            // 5.1 创建HTTP请求对象
            HttpRequest httpRequest = this.executeHttpRequest(serviceConfigInfo);
            response.setRequestUrl(this.requestUrl);
            response.setRequestMethod(httpRequest.getMethod().name());
            response.setRequestHeaderJson(JSONUtil.toJsonStr(httpRequest.headers()));

            // 5.2 执行Http请求，获取响应对象
            HttpResponse httpResponse = httpRequest.execute();

            // 5.3 处理HTTP响应头，转为JSON
            Map<String, List<String>> respHeaders = new HashMap<>(httpResponse.headers());
            if (respHeaders.containsKey(null)) {
                // 毫无疑问的是，在HTTP响应头的第一行，它的key总是null，为了逻辑上的严谨性需要添加一个if判断
                respHeaders.put("line-1st", respHeaders.get(null));
                // 在将Map对象序列化为JSON的过程中，若key为null则可能引发异常，此处将key改为`line-1st`是为了下面顺利的拿到JSON便于存储
                respHeaders.remove(null);
            }

            // 5.4 获取HTTP请求的响应内容
            response.setResponseHeaderJson(JSONUtil.toJsonStr(respHeaders));
            response.setResponseBodyJson(httpResponse.body());
        } catch (Exception e) {
            String message = e.getMessage();
            message = message == null ? e.getClass().getName() : message;
            StringBuilder errorStackTrace = new StringBuilder(message);
            for (StackTraceElement element : e.getStackTrace()) {
                errorStackTrace.append("\r\n\r\tat ").append(element.toString());
            }

            // 包装DSM-SSO模块异常响应对象
            Map<String, Object> responseMap = new HashMap<>();
            responseMap.put(HttpServiceFieldConstant.ERR_CODE, HttpStatus.INTERNAL_SERVER_ERROR.value());
            responseMap.put(HttpServiceFieldConstant.ERR_MSG, HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase());

            response.setResponseHeaderJson(null);
            response.setResponseBodyJson(JSONUtil.toJsonStr(responseMap));
            response.setIsSuccess(IsSuccessEnum.FAILURE);
            response.setExceptionStack(String.valueOf(errorStackTrace));
        }

        // 5.5 返回响应内容
        return response;
    }

    /**
     * 根据 配置逻辑 执行 HTTP 请求
     *
     * @param serviceConfigInfo HTTP请求配置
     * @return 返回 执行 HTTP 请求 响应结果
     */
    public abstract HttpRequest executeHttpRequest(ServiceConfigInfo serviceConfigInfo) throws Exception;

}
